package com.goldsign.pay.common.util;


import com.goldsign.pay.common.log.SysLog;
import org.apache.log4j.Logger;

import java.io.*;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 转换工具类
 */
public class Converter {
	protected final static Logger logger = Logger.getLogger(Converter.class);
	private static final int PAD_LIMIT = 8192;
	private static final String[] PADDING = new String[Character.MAX_VALUE];
	
	public static String intToStr(Integer i){
		
		if(null == i){
			return null;
		}
		
		return i.toString();
	}
	
	public static String intToStr(Integer i, String fmt){
	
		return numToStr(i, fmt);
	}

	public static Integer strToInt(String str){
		
		if(null == str){
			return null;
		}
		
		try{
			return Integer.parseInt(str);
		}catch(Exception e){
			return null;
		}
	}
	
	public static Integer strToInt(String str, String fmt){
		
		Number num = strToNum(str, fmt);
		
		if(null == num){
			return null;
		}
		
		return num.intValue();
	}
	
	public static Long strToLong(String str){
		
		if(null == str){
			return null;
		}
		
		try{
			return Long.parseLong(str);
		}catch(Exception e){
			return null;
		}
	}
	
	public static Long strToLong(String str, String fmt){
		
		Number num = strToNum(str, fmt);
		
		if(null == num){
			return null;
		}
		
		return num.longValue();
	}
	
	public static String longToStr(Long l){
		
		if(null == l){
			return null;
		}
		
		return l.toString();
	}
	
	public static String longToStr(Long l, String fmt){
		
		return numToStr(l, fmt);
	}
	
	public static Double strToDouble(String str){
		
		if(null == str){
			return null;
		}
		
		try{
			return Double.parseDouble(str);
		}catch(Exception e){
			return null;
		}
	}
	
	public static Double strToDouble(String str, String fmt){
		
		Number num = strToNum(str, fmt);
		
		if(null == num){
			return null;
		}
		
		return num.doubleValue();
	}
	
	public static String doubleToStr(Double d){
		
		if(null == d){
			return null;
		}
		
		return d.toString();
	}
	
	public static String doubleToStr(Double d, String fmt){
		
		return numToStr(d, fmt);
	}
	
	public static Float strToFloat(String str){
		
		if(null == str){
			return null;
		}
		
		try{
			return Float.parseFloat(str);
		}catch(Exception e){
			return null;
		}
	}
	
	public static Float strToFloat(String str, String fmt){
		
		Number num = strToNum(str, fmt);
		
		if(null == num){
			return null;
		}
		
		return num.floatValue();
	}
	
	public static String floatToStr(Float f){
		
		if(null == f){
			return null;
		}
		
		return f.toString();
	}
	
	public static String floatToStr(Float f, String fmt){
		
		return numToStr(f, fmt);
	}
	
	public static Number strToNum(String str, String fmt){
		
		DecimalFormat fmter = new DecimalFormat(fmt);
		
		try{
			Number num = fmter.parse(fmt);
			
			return num;
		}catch(Exception e){
			return null;
		}
	}
	
	public static String numToStr(Number n, String fmt){
		
		if(null == n){
			return null;
		}
		if(null == fmt){
			return n.toString();
		}
		fmt = fmt.trim();
		if(fmt.equals("")){
			return n.toString();
		}
		
		DecimalFormat fmter =new DecimalFormat(fmt);
		
		return fmter.format(n);
	}
	
	public static String booleanToStr(Boolean b){
		
		if(null == b){
			return null;
		}
		
		return b.toString();
	}
	
	public static Boolean strToBoolean(String str){
		
		if(null == str){
			return null;
		}
		str = str.trim();
		try{
			return Boolean.parseBoolean(str);
		}catch(Exception e){
			return null;
		}
	}
	
	private static String getDateFmterH(String str){
		
		String fmt = null;
		switch(str.length()){
			case 4:{
				fmt = "yyyy";
				break;
			}case 7:{
				fmt = "yyyy-MM";
				break;
			}case 10:{
				fmt = "yyyy-MM-dd";
				break;
			}case 13:{
				fmt = "yyyy-MM-dd HH";
				break;
			}case 16:{
				fmt = "yyyy-MM-dd HH:mm";
				break;
			}case 19:{
				fmt = "yyyy-MM-dd HH:mm:ss";
				break;
			}default:{
				fmt = "yyyy-MM-dd HH:mm:ss";
			}
		}
		
		return fmt;
	}
	
	private static String getDateFmterS(String str){
		
		String fmt = null;
		switch(str.length()){
			case 4:{
				fmt = "yyyy";
				break;
			}case 7:{
				fmt = "yyyy/MM";
				break;
			}case 10:{
				fmt = "yyyy/MM/dd";
				break;
			}case 13:{
				fmt = "yyyy/MM/dd HH";
				break;
			}case 16:{
				fmt = "yyyy/MM/dd HH:mm";
				break;
			}case 19:{
				fmt = "yyyy/MM/dd HH:mm:ss";
				break;
			}default:{
				fmt = "yyyy/MM/dd HH:mm:ss";
			}
		}
		
		return fmt;
	}
	
	private static String getDateFmterD(String str){
		
		String fmt = null;
		switch(str.length()){
			case 4:{
				fmt = "yyyy";
				break;
			}case 7:{
				fmt = "yyyy.MM";
				break;
			}case 10:{
				fmt = "yyyy.MM.dd";
				break;
			}case 13:{
				fmt = "yyyy.MM.dd HH";
				break;
			}case 16:{
				fmt = "yyyy.MM.dd HH:mm";
				break;
			}case 19:{
				fmt = "yyyy.MM.dd HH:mm:ss";
				break;
			}default:{
				fmt = "yyyy.MM.dd HH:mm:ss";
			}
		}
		
		return fmt;
	}
	
	private static String getDateFmterZ(String str){
		
		String fmt = null;
		switch(str.length()){
			case 5:{
				fmt = "yyyy年";
				break;
			}case 8:{
				fmt = "yyyy年MM月";
				break;
			}case 11:{
				fmt = "yyyy年MM月dd日";
				break;
			}case 14:{
				fmt = "yyyy年MM月dd日HH时";
				break;
			}case 15:{
				fmt = "yyyy年MM月dd日 HH时";
				break;
			}case 17:{
				fmt = "yyyy年MM月dd日HH时mm分";
				break;
			}case 18:{
				fmt = "yyyy年MM月dd日 HH时mm分";
				break;
			}case 20:{
				fmt = "yyyy年MM月dd日HH时mm分ss秒";
				break;
			}case 21:{
				fmt = "yyyy年MM月dd日 HH时mm分ss秒";
				break;
			}default:{
				fmt = "yyyy年MM月dd日  HH时mm分ss秒";
			}
		}
		
		return fmt;
	}
	
	private static String getDateFmterN(String str){

		String fmt = null;
		switch(str.length()){
			case 4:{
				fmt = "yyyy";
				break;
			}case 6:{
				fmt = "yyyyMM";
				break;
			}case 8:{
				fmt = "yyyyMMdd";
				break;
			}case 11:{
				fmt = "yyyyMMdd HH";
				break;
			}case 14:{
				fmt = "yyyyMMdd HH:mm";
				break;
			}case 17:{
				fmt = "yyyyMMdd HH:mm:ss";
				break;
			}default:{
				fmt = "yyyyMMdd HH:mm:ss";
			}
		}
		
		return fmt;
	}
	
	private static String getDateFmter(String str){
		
		String fmt = null;
		if(str.contains("-")){
			fmt = getDateFmterH(str);
		}else if(str.contains("/")){
			fmt = getDateFmterS(str);
		}else if(str.contains(".")){
			fmt = getDateFmterD(str);
		}else if(str.contains("年")){
			fmt = getDateFmterZ(str);
		}else{
			fmt = getDateFmterN(str);
		}
		
		return fmt;
	}
	
	public static Date strToDate(String str){
		
		if(null == str){
			return null;
		}
		str = str.trim();
		if(str.equals("")){
			return null;
		}
		String fmt = getDateFmter(str);
		
		return strToDate(str, fmt);
	}

	public static Date strToDate(String str, String fmt){
		
		SimpleDateFormat fmter = new SimpleDateFormat(fmt);
		try{
			return fmter.parse(str.trim());
		}catch(Exception e){
			return null;
		}
	}
	
	public static String strToDateStr(String str, String nFmt){
		
		Date date = strToDate(str);
		if(null == date){
			return str;
		}
		if(null == nFmt){
			return str;
		}
		SimpleDateFormat fmter = new SimpleDateFormat(nFmt);
	
		return fmter.format(date);
		
	}
	
	public static String strToDateStr(String str, String oFmt, String nFmt) {
		
		Date date = strToDate(str, oFmt);
		
		return dateToStr(date, nFmt);
	}
	
	public static String dateToyyyyMMddStr(Date date){
		return dateToStr(date, "yyyy-MM-dd");
	}
	
	public static String dateToHHmmSStr(Date date){
		
		return dateToStr(date, "HH:mm:ss");
	}
	
	public static String dateToyyyyMMddHHmmSStr(Date date){
		
		return dateToStr(date, "yyyy-MM-dd HH:mm:ss");
	}
	
	public static String dateToStr(Date date, String fmt){
		
		if(null == date){
			return null;
		}
		if(null == fmt){
			return date.toString();
		}
		
		SimpleDateFormat fmter = new SimpleDateFormat(fmt);
		
		return fmter.format(date);
	}
	
	public static Timestamp strToTimestamp(String str) {

		Date date = null;
		
		date = strToDate(str);
		if(null != date){
			return new Timestamp(date.getTime());
		}else{
			return null;
		}
		
	}
	
	/**
	 * 获得星期几的中文描述
	 * @param date
	 * @return
	 */
	public static String dateToDayStr(Date date){
		if(null == date){
			return null;
		}
		String[] day = new String[]{"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		Calendar cal = getCalendar(date);
		return day[cal.get(Calendar.DAY_OF_WEEK)];
	}
	
	public static String getCurDateYYYYmmDD(){
		
		return dateToyyyyMMddStr(new Date());
	}
	
	public static String getCurDateHHmmSS(){
		
		return dateToHHmmSStr(new Date());
	}
	
	public static String getCurDateYYYYmmDDHHmmSS(){
		
		return dateToyyyyMMddHHmmSStr(new Date());
	}
	
	/**
	 * 获得date的Calendar对象
	 * @param date
	 * @return
	 */
	private static Calendar getCalendar(Date date){
		Calendar cal = Calendar.getInstance(); 
		if(null != date)
			cal.setTime(date); 
		return cal;
	}
	
	/*
	 * 取月的第一天
	 */
	public static Date getFirstDayOfMonth(Date date) {
		Calendar cal = getCalendar(date);
		cal.set(Calendar.DAY_OF_MONTH, 1); 
		return cal.getTime(); 
	} 
	
	/*
	 * 取月的最后一天
	 */
	public static Date getLastDayOfMonth(Date date) { 
		Calendar cal = getCalendar(date);
		cal.set(Calendar.DAY_OF_MONTH, 1); 
		cal.add(Calendar.MONTH, 1); 
		cal.add(Calendar.DATE, -1);
		return cal.getTime(); 
	}
	
	public static Date getDateAfterByDate(Date date, int days){
		
		Date dateRet = null;
		
		if(date == null)
			return null;
		
		long betInt = date.getTime()+days*24*60*60*1000L;
		dateRet = new Date(betInt);
			
		return dateRet;
	}
	
	public static String objToStrN(Object obj){
		
		if(null == obj){
			return null;
		}
		
		return obj.toString();
	}
	
	public static String objToStrE(Object obj){
		
		if(null == obj){
			return "";
		}
		
		return obj.toString();
	}
	
	public static String gbkToIso(String str){
		
		try {
			return new String(str.getBytes("GBK"), "ISO-8859-1");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String isoToGbk(String str){
		
		try {
			return new String(str.getBytes("ISO-8859-1"), "GBK");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String utfToGbk(String str){
		
		try {
			return new String(str.getBytes("UTF-8"), "GBK");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String gbkToUtf(String str){
		
		try {
			return new String(str.getBytes("GBK"), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String isoToUtf(String str){
		
		try {
			return new String(str.getBytes("ISO-8859-1"), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String utfToIso(String str){
		
		try {
			return new String(str.getBytes("UTF-8"), "ISO-8859-1");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String strToStrEnDe(String str, String en, String de){
		
		try {
			return new String(str.getBytes(en), de);
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String encodeUtfStr(String str){
		
		try {
			return URLEncoder.encode(str, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
		
	}
	
	public static String decodeUtfStr(String str){
		
		try {
			return URLDecoder.decode(str, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String encodeStr(String str, String en){
		
		try {
			return URLEncoder.encode(str, en);
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}
	
	public static String decodeStr(String str, String de){
		
		try {
			return URLDecoder.decode(str, de);
		} catch (UnsupportedEncodingException e) {
			return str;
		}
	}

	public static Map<String, Object> objToMap(Object obj){
		
		Map<String, Object> keyValues = new HashMap<String, Object>();
		
		Field[] fields = obj.getClass().getDeclaredFields();
		for (Field field : fields) {
			Object fieldValue = null;
			field.setAccessible(true);
			try {
				fieldValue = field.get(obj);
				if (null != fieldValue) {
					keyValues.put(field.getName(), fieldValue);
				}
			} catch (Exception e) {
				SysLog.info(e);
			}
		}
		
		return keyValues;
	}
	
	public static List<Map> collectionToListMap(Collection source){
		
		List<Map> datas = new ArrayList<Map>();
		for(Object obj: source){
			if(null == obj){
				continue;
			}
			Map map = null;
			if(obj instanceof String || obj instanceof Number){
				map = new LinkedHashMap();
				map.put("code", obj);
				map.put("name", obj);
			}else if(obj instanceof Map){
				map = (Map) obj;
			}else{
				map = voToMap(obj);
			}
			datas.add(map);
		}
		
		return datas;
	}
	
	public static Map voToMap(Object vo) {
		
		Map map = new HashMap();
		
		Field[] fields = vo.getClass().getDeclaredFields();
		for (Field field : fields) {
			String name = field.getName();
			if(null == name){
				continue;
			}
			field.setAccessible(true);
			Object value = null;
			try {
				value = field.get(vo);
			} catch (Exception e) {
				SysLog.info(e);
			}
			if (value != null) {
				map.put(name, value);
			}
		}
		
		return map;
	}
	
	public static String objToStr(Object object){
		
		if(object==null){
			return "";
		}else if(object instanceof Collection){
			StringBuffer buf = new StringBuffer("");
			Collection col = (Collection)object;
			for(Object subObject : col){
				buf.append(subObject);
				buf.append(",");
			}
			if(col.size() > 0){
				buf.delete(buf.length()-1, buf.length());
			}
			return buf.toString();
		}else if(object instanceof Object[]){
			StringBuffer buf = new StringBuffer("");
			Object[] arr = (Object[])object;
			for(Object subObject : arr){
				buf.append(subObject);
				buf.append(",");
			}
			if(arr.length > 0){
				buf.delete(buf.length()-1, buf.length());
			}
			return buf.toString();
		}else{
			return object.toString();
		}
	}
	
	public static String getFileExtention(String fileName) {
		
		String fileExtend = "";
		if(null == fileName){
			return fileExtend;
		}
		int pos = fileName.lastIndexOf(".");
		if(pos != -1){
			fileExtend = fileName.substring(pos+1);
		}
		return fileExtend;
	}
	
	public static void copy(File src, File dst) {
		
		int BUFFER_SIZE = 16 * 1024;
		InputStream in = null;
		OutputStream out = null;
		try {
			try {
				in = new BufferedInputStream(new FileInputStream(src),
						BUFFER_SIZE);
				out = new BufferedOutputStream(new FileOutputStream(dst),
						BUFFER_SIZE);
				byte[] buffer = new byte[BUFFER_SIZE];
				while (in.read(buffer) > 0) {
					out.write(buffer);
				}
			} finally {
				if (null != in) {
					in.close();
				}
				if (null != out) {
					out.close();
				}
			}
		} catch (Exception e) {
			SysLog.info(e);
		}
	}
	
	public static String NoHTML(String htmlstring) {

		if (htmlstring == null) {
			return null;
		}

		// 删除脚本
		Pattern.compile("(?s)<\\s*script[^>]*?>.*?<\\s*/script\\s*>", Pattern.CASE_INSENSITIVE).matcher(htmlstring)
				.replaceAll("");
		// 删除HTML
		htmlstring = Pattern.compile("<\\s*(br|p).*?>", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("[br]");
		htmlstring = Pattern.compile("(?s)<(.[^>]*?)>", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("");
		htmlstring = Pattern.compile("([\\r\\n])[\\s]+", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("");
		htmlstring = Pattern.compile("-->", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("");
		htmlstring = Pattern.compile("<!--.*", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("");

		htmlstring = Pattern.compile("&(quot|#34);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("\"");
		htmlstring = Pattern.compile("&(amp|#38);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("&");
		htmlstring = Pattern.compile("&(lt|#60);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("<");
		htmlstring = Pattern.compile("&(gt|#62);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll(">");
		htmlstring = Pattern.compile("&(nbsp|#160);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("   ");
		htmlstring = Pattern.compile("&(iexcl|#161);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("\\xa1");
		htmlstring = Pattern.compile("&(cent|#162);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("\\xa2");
		htmlstring = Pattern.compile("&(pound|#163);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("\\xa3");
		htmlstring = Pattern.compile("&(copy|#169);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("\\xa9");
		htmlstring = Pattern.compile("&#(\\d+);", Pattern.CASE_INSENSITIVE).matcher(htmlstring).replaceAll("");
		//htmlstring = htmlstring.replaceAll("[br]", "\r\n");

		return htmlstring;
	}
	
	public static String emptyToNull(String str){
		if(Converter.isStrEmpty(str)){
			return null;
		}else{
			return str.trim();
		}
	}


	public static boolean isStrEmpty(String str) {

		if (null == str) {
			return true;
		}
		str = str.trim();
		if (str.equals("")) {
			return true;
		}

		return false;
	}
	
	public static Object getObjectValue(Object obj, String fieldName){
		
		Object value = null;
		
		try{
			int index = fieldName.indexOf(".");
			while(index != -1){
				obj = getObjectValue(obj, fieldName.split("\\.")[0]);
				fieldName = fieldName.substring(index+1);
				index = fieldName.indexOf(".");
			}
			Field field = obj.getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			value = field.get(obj);
			
		}catch(Exception e){	
			value = null;
		}
		
		return value;
	}

    /**
     * <p>Left pad a String with a specified character.</p>
     * <p/>
     * <p>Pad to a size of <code>size</code>.</p>
     * <p/>
     * <pre> 前缀加指定字符
     * StringUtil.leftPad("bat", 5, 'z')  = "zzbat"
     * </pre>
     * @since 2.0
     */
	public static String leftPad(String str, int size, char padChar) {
        if (str == null) {
            return null;
        }
        int pads = size - str.length();
        if (pads <= 0) {
            return str; // returns original String when possible
        }
        if (pads > PAD_LIMIT) {
            return leftPad(str, size, String.valueOf(padChar));
        }
        return padding(pads, padChar).concat(str);
    }
	
	
	/**
     * <p>Left pad a String with a specified String.</p>
     * <p/>
     * <p>Pad to a size of <code>size</code>.</p>
     * <p/>
     * <pre> 格式化字符串，不够位数补指定字符
     * </pre>
     */
	public static String leftPad(String str, int size, String padStr) {
        if (str == null) {
            return null;
        }
        if (isEmpty(padStr)) {
            padStr = " ";
        }
        int padLen = padStr.length();
        int strLen = str.length();
        int pads = size - strLen;
        if (pads <= 0) {
            return str; // returns original String when possible
        }
        if (padLen == 1 && pads <= PAD_LIMIT) {
            return leftPad(str, size, padStr.charAt(0));
        }

        if (pads == padLen) {
            return padStr.concat(str);
        } else if (pads < padLen) {
            return padStr.substring(0, pads).concat(str);
        } else {
            char[] padding = new char[pads];
            char[] padChars = padStr.toCharArray();
            for (int i = 0; i < pads; i++) {
                padding[i] = padChars[i % padLen];
            }
            return new String(padding).concat(str);
        }
    }
	 /**
     * <p>Returns padding using the specified delimiter repeated
     * to a given length.</p>
     * <p/>
     * <pre>
     * StringUtil.padding(3, 'e')  = "eee"
     * </pre>
     * 将一个字符格式化成指定长度
     * @param repeat  number of times to repeat delim
     * @param padChar character to repeat
     */
    private static String padding(int repeat, char padChar) {
        // be careful of synchronization in this method
        // we are assuming that get and set from an array index is atomic
        String pad = PADDING[padChar];
        if (pad == null) {
            pad = String.valueOf(padChar);
        }
        while (pad.length() < repeat) {
            pad = pad.concat(pad);
        }
        PADDING[padChar] = pad;
        return pad.substring(0, repeat);
    }

//  判断是否为空
    public static boolean isEmpty(String str) {
        return ((str == null) || (str.length() == 0));
    }
    
	public static String fmtStrBf(String str, String fillC, int len){
		
		if(null == str){
			return str;
		}
		int bLen = str.getBytes().length;
		int cLen = len-bLen;
		for(int i=0; i<cLen; i++){
			str = fillC + str;
		}
		
		return str;
	}
	
	public static String fmtStrAf(String str, String fillC, int len){
		
		if(null == str){
			return str;
		}
		int bLen = str.getBytes().length;
		int cLen = len-bLen;
		for(int i=0; i<cLen; i++){
			str += fillC;
		}
		
		return str;
	}
	
}
